<template>
    <a-modal
        v-bind="defaultModalProps"
        :open="open"
        :width="736"
        class="work-address-action-modal"
        :body-style="{paddingInline: '32px'}"
        @cancel="handleCancel"
    >
        <template #title>
            <header class="text-sm font-normal flex flex-col gap-[2px] justify-center px-4 border-b border-solid border-b-[#F4F6FC]" style="height: 70px;">
                <h5 class="text-primary">添加地址</h5>
                <p class="text-[#ACAEB2]">请填写真实有效地址，若查实造假，账号将被冻结</p>
            </header>
        </template>
        <template #footer>
            <a-flex align="center" :gap="20" justify="flex-end">
                <a-button type="primary" size="large" style="padding-inline: 40px;" :disabled="actionDisabled" class="disabled:!bg-theme/60 disabled:!text-white" @click="handleSave()">
                    保存
                </a-button>
            </a-flex>
        </template>
        <div class="mt-6 overflow-hidden mb-12">
            <div class="h-[200px] flex flex-row items-center justify-between">
                <section class="flex flex-col gap-5">
                    <a-flex align="center" :gap="12">
                        <label class="text-sm text-primary">工作城市</label>
                        <a-cascader v-model:value="formState.areaValue" :options="areaOptions" :fieldNames placeholder="请选择城市" size="large" style="width: 280px;" @change="handleAreaChange" />
                    </a-flex>
                    <a-flex align="center" :gap="12">
                        <label class="text-sm text-primary">工作地点</label>
                        <GpSearchableSelect :disabled="placeDisabled" v-model:value="formState.place" placeholder="请输入办公大楼" size="large" style="width: 280px;" mode="single" :get-options="getPlaceOptions" @change="handlePlaceChange" />
                    </a-flex>
                    <a-flex align="center" :gap="12">
                        <label class="text-sm text-primary">详细地址</label>
                        <a-input :disabled="addressDisabled" v-model:value="formState.address" placeholder="楼层/单元室/门牌号" size="large" style="width: 280px;" />
                    </a-flex>
                </section>
                <section class="h-full w-[300px] relative">
                    <div v-if="showMask" class="size-full bg-[url(/images/map-no-address.png)] bg-cover absolute inset-0 z-10" @wheel.stop="" @click.stop="" @contextmenu.stop=""></div>
                    <BaiduMap class="size-full" v-bind="defaultMapProps" :center>
                        <BmMarker :position="center" :icon>
                            <BmOverlay ref="overlayRef" pane="labelPane" class="overlay-pane" @draw="draw">
                                <div class="arbitrary">
                                    <p class="maxline2 w-full">
                                        {{ overlayContent }}
                                    </p>
                                </div>
                            </BmOverlay>
                        </BmMarker>
                    </BaiduMap>
                </section>
            </div>
        </div>
    </a-modal>
</template>
<script lang="ts" setup>
import { BaiduMap, BmOverlay, BmMarker } from 'vue-baidu-map-3x';
import { defaultModalProps, defaultMapProps, defCenter } from '@/constants/comp-setting';
import type { Exposed } from './types';
import type { ValueType } from 'ant-design-vue/es/vc-cascader/Cascader';
import type { DefaultOptionType } from 'ant-design-vue/es/select';
import type { Region } from '@/api/siderBar/model';
import { postJobAddjobaddress } from '@/api/siderBar/job';
import { message } from 'ant-design-vue';

type FormState = {
    areaValue?: any
    area?: Region
    place?: string
    address?: string
}
interface PlaceOption extends IOption<string> {
    lng: number
    lat: number
    title: string
    address: string
}
defineOptions({
    name: 'WorkAdressActionModal',
    inheritAttrs: false
})
defineExpose<Exposed>({
    open() {
        open.value = true
    },
})
const emit = defineEmits<{
    success: []
}>()
const open = ref(false)
const { data: areaOptions } = useFetchAreas()
const fieldNames = {
    label: "name",
    value: "id",
    children: "children"
}
const loading = ref(false)
const formState = ref(getInitialState())
const placeDisabled = computed(() => !formState.value.area)
const addressDisabled = computed(() => !formState.value.place)
const actionDisabled = computed(() => {
    const { area, place, address } = toValue(formState)
    return Boolean(loading.value || !area || !place || !address)
})
const showMask = computed(() => !formState.value.place)
const localSearchInstance = shallowRef<any>(null)
let localSearchResolveFn: IFn | null = null
const center = ref(defCenter)
const overlayContent = computed(() => {
    const contents: string[] = []
    const { area, place, address } = toValue(formState)
    if (area) {
        const point = area.fullName!.split(',').slice(1).join('');
        contents.push(point)
    }
    if (place) {
        const [,,title] = place.split(',')
        contents.push(title)
    }
    let _address = address?.trim()
    if (_address) {
        contents.push(_address)
    }
    return contents.join('')
})
const overlayRef = ref()
useEffectScope(() => {
    watch(overlayContent, () => {
        if (overlayRef.value) {
            overlayRef.value.reload()
        }
    })
})
const overlayWidth = ref(200)
const icon = {
    url: '/images/map-marker.png', 
    size: {
        width: 24, 
        height: 24
    },
    opts: {
        anchor: {
            width: 16,
            height: 32
        }
    }
}
function draw({ el, BMap, map }: any) {
    if (showMask.value) return
    const { lng, lat } = toValue(center)
    const pixel = map.pointToOverlayPixel(new BMap.Point(lng, lat))
    const width = overlayWidth.value || el.getBoundingClientRect().width
    el.style.left = pixel.x - width / 2 + 'px'
    el.style.top = pixel.y - 86 + 'px'
    if (!overlayWidth.value && width) {
        overlayWidth.value = width
    }
};
function getInitialState(): FormState {
    return {}
}
function handleAreaChange(_: ValueType, selectOptions: DefaultOptionType[]) {
 if (selectOptions) {
    const [, , area] = selectOptions
    formState.value.area = <Region>area
 } else {
    formState.value.area = void 0
 }
 initializeLocalSearch()
}
function initializeLocalSearch() {
    const { area } = toValue(formState)
    if (!area) {
        localSearchInstance.value = null
    } else if ('BMap' in window) {
        const point = area.fullName!.split(',').slice(1).join('');
        localSearchInstance.value = new BMap.LocalSearch(point, {
            onSearchComplete: function (results: any) {
                try {
                    const status = localSearchInstance.value.getStatus();
                    if (status === BMAP_STATUS_SUCCESS) {
                        const count = results.getCurrentNumPois();
                        const opts: PlaceOption[] = [];
                        for (let i = 0; i < count; i++) {
                            const pio = results.getPoi(i);
                            if (pio) {
                                opts.push({
                                    lng: pio.point.lng,
                                    lat: pio.point.lat,
                                    title: pio.title,
                                    address: pio.address,
                                    value: [pio.point.lng, pio.point.lat, pio.title].join(','),
                                    label: pio.title
                                });
                            }
                        }
                        console.log('opts', opts);
                        callback(opts)
                    } else {
                        callback([])
                    }
                } catch (error) {
                    console.log(error);
                    callback([])
                }
                function callback(opts: Array<PlaceOption>) {
                    if (typeof localSearchResolveFn === 'function') {
                        localSearchResolveFn(opts)
                    }
                }
            },
        })
    }
}
function getPlaceOptions(text: string) {
    text = text.trim()
    if (!("BMap" in window) || !text) return Promise.resolve([])
    return new Promise(resolve => {
        localSearchResolveFn = resolve
        if (localSearchInstance.value) {
            localSearchInstance.value.search(text, {
                forceLocal: true
            })
        }
    })
}
function handlePlaceChange(_: string, option: PlaceOption) {
    if (!option) {
        formState.value.place = void 0;
    } else {
        center.value = {
            lng: option.lng,
            lat: option.lat
        }
    }
}
async function handleSave() {
    console.log(formState.value)
    const { area, place, address } = toValue(formState)
    try {
        loading.value = true
        const [lng, lat, _place] = place!.split(",")
        await postJobAddjobaddress({
            regionId: area!.id,
            address: _place + address,
            lng: Number(lng),
            lat: Number(lat)
        })
        message.success('添加成功')
        handleCancel()
        emit("success")
    } catch (error) {
        console.log(error)
        loading.value = false
    }
}
function handleCancel() {
    open.value = false
    loading.value = false
    formState.value = getInitialState()
    localSearchInstance.value = null
    localSearchResolveFn = null
    center.value = defCenter
}
</script>
<style lang="less" scoped>
:global(.work-address-action-modal .ant-modal-content) {
    padding-inline: 0 !important;
    padding-block-start: 0 !important;
}
:global(.work-address-action-modal .ant-modal-footer) {
    padding-inline: 32px;
}
.overlay-pane {
    position: absolute;
    box-sizing: border-box;
    width: 200px;
    height: 40px;
    overflow: visible;
    .arbitrary {
        border-radius: 8px;
        background-color: #ffffff;
        width: max-content;
        max-width: 260px;
        height: auto;
        max-height: 68px;
        padding-inline: 16px;
        padding-block: 12px;
        color: var(--color-primary);
        font-size: 14px;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
        box-sizing: border-box;
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
    }
    &::after {
        content: "";
        display: block;
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translate(-50%, 100%);
        width: 16px;
        height: 16px;
        box-sizing: border-box;
        border: 8px solid transparent;
        border-block-start-color: #ffffff;
    }
}
</style>
